package com.woniu.service.impl;

import com.woniu.dto.CreateExamRequestDTO;
import com.woniu.entity.*;
import com.woniu.mapper.CheckDetailMapper;
import com.woniu.mapper.CheckFeeDetailMapper;
import com.woniu.mapper.ExamMapper;
import com.woniu.mapper.InpatientRecordMapper;
import com.woniu.service.ExamService;
import com.woniu.utils.ResponseEnum;
import com.woniu.utils.ResponseUtil;
import com.woniu.utils.UserContext;
import com.woniu.vo.ExamItemVO;
import com.woniu.vo.PatientExamVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class ExamServiceImpl implements ExamService {
    @Resource
    private ExamMapper examMapper;
    @Resource
    private CheckDetailMapper checkDetailMapper;
    @Resource
    private InpatientRecordMapper inpatientRecordMapper;
    @Resource
    private CheckFeeDetailMapper checkFeeDetailMapper;
    @Override
    public ResponseUtil listAllItems() {
        List<ExamItemVO> examItems = examMapper.findAllExamItems();
        return examItems.size() > 0 ?
                ResponseUtil.get(ResponseEnum.OK,examItems)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil listExamsByPatient(Integer patientId) {
        List<PatientExamVO> examsByPatientId
                = examMapper.findExamsByPatientId(patientId);
        return examsByPatientId.size() > 0 ?
                ResponseUtil.get(ResponseEnum.OK,examsByPatientId)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseUtil createInpatientExams(CreateExamRequestDTO dto) throws ParseException {
        if (dto.getExamItemIds() == null || dto.getExamItemIds().isEmpty()) {
            return ResponseUtil.get(ResponseEnum.EMPTY_EXAM_ITEM_ID);
        }

        Integer loggedInDoctorId = UserContext.ContextUserId();
        Date now = new Date();
        String finalStatus; // 最终状态（住院/门诊）

        //  财务计算
        BigDecimal totalPrice = BigDecimal.ZERO;
        String allItemNames = ""; // 用于写入费用明细

        // 获取所有选中项目的价格
        List<ExamItem> items = examMapper.findItemsByIds(dto.getExamItemIds());
        if (items.size() != dto.getExamItemIds().size()) {
            throw new RuntimeException("部分检查项目不存在或已下架，操作回滚");
        }

        // 计算总价
        StringBuilder itemNamesBuilder = new StringBuilder();
        for (ExamItem item : items) {
            totalPrice = totalPrice.add(item.getPrice());
            itemNamesBuilder.append(item.getItemName()).append(", ");
        }
        allItemNames = itemNamesBuilder.length() > 0 ?
                itemNamesBuilder.substring(0, itemNamesBuilder.length() - 2) : "";

        //  财务校验与扣费 (仅限住院)
        if ("1".equals(dto.getType())) {
            // 1 检查押金是否充足
            InpatientRecord record = inpatientRecordMapper.findActiveRecordByPatientId(dto.getPatientId());
            if (record == null) {
                return ResponseUtil.get(ResponseEnum.FAIL, "扣费失败：未找到患者的在院记录");
            }
            if (record.getHzBalance().compareTo(totalPrice) < 0) {
                String msg = String.format("押金不足，开检查失败！(余额: %.2f, 需: %.2f)",
                        record.getHzBalance().doubleValue(),
                        totalPrice.doubleValue());
                return ResponseUtil.get(ResponseEnum.FAIL, msg);
            }

            // 2 尝试扣费
            int feeRows = inpatientRecordMapper.deductBalance(dto.getPatientId(), totalPrice);
            if (feeRows == 0) {
                // 扣费失败 (并发或余额不足)
                return ResponseUtil.get(ResponseEnum.FAIL, "押金扣除失败，请重试");
            }

            // 住院病人已扣费，状态设为 '1' (已缴费)
            finalStatus = "1";

        } else {
            // 门诊病人，状态设为 '0' (未缴费)
            finalStatus = "0";
        }

        // 插入主表 (ck_detail) ---
        CheckDetail checkDetail = new CheckDetail();
        checkDetail.setCkCaseid(dto.getPatientId());
        checkDetail.setCkWorkerid(loggedInDoctorId);
        checkDetail.setCkDate(now);
        checkDetail.setCkStatus(finalStatus);
        checkDetail.setCkType(dto.getType());
        checkDetailMapper.insert(checkDetail);

        Integer newCheckDetailId = checkDetail.getId();
        if (newCheckDetailId == null || newCheckDetailId == 0) {
            throw new RuntimeException("创建检查申请单失败，无法获取主键ID");
        }

        // 记录费用流水 (仅限住院)
        if ("1".equals(dto.getType())) {
            CheckFeeDetail fee = new CheckFeeDetail();
            fee.setCfCheckid(newCheckDetailId); // 关联到 ck_detail.id
            fee.setCfPrice(totalPrice);
            fee.setCfProjectname(allItemNames);
            fee.setCfCaseid(dto.getPatientId());
            fee.setCfDate(now);
            checkFeeDetailMapper.insertSelective(fee);
        }

        //  批量插入从表 (patient_exam)
        List<PatientExam> examList = new ArrayList<>();
        for (Integer itemId : dto.getExamItemIds()) {
            PatientExam pe = new PatientExam();
            pe.setPatientId(dto.getPatientId());
            pe.setExamItemId(itemId);
            pe.setExamId(newCheckDetailId);
            pe.setStatus(Integer.valueOf(finalStatus));
            pe.setCreateTime(now);
            examList.add(pe);
        }

        Integer result = examMapper.batchInsertPatientExams(examList); //
        return result > 0 ? ResponseUtil.get(ResponseEnum.OK, result)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }
}
